home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libcan / canblend.c next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  20.7 KB  |  1,063 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    canblend -
  19.  *        Blend rows and columns into the canvas.
  20.  *
  21.  *                Paul Haeberli - 1991
  22.  *
  23.  *      exports 
  24.  *
  25.     void beginstroke()
  26.     void endstroke()
  27.     void setnegalpha(v)
  28.     void setclonemode(c)
  29.     void setcurcolor(c)
  30.     unsigned long getcurcolor()
  31.     void avg_clear();
  32.     long avg_get();
  33.     void clonesource(c,dx,dy)
  34.     void readpix_init()
  35.     void setblend(b)
  36.     int getblend()
  37.  *
  38.  */
  39. #include "stdio.h"
  40. #include "canvas.h"
  41. #include "lum.h"
  42.  
  43. void (*constblendrow)();
  44. void (*blendrow)();
  45. void (*blendcol)();
  46.  
  47. static void writepix_constblendrow();
  48. static void writepix_blendrow();
  49. static void writepix_blendcol();
  50.  
  51. /* lum macros */
  52.  
  53. #define NOTHING        (-1)
  54. #define DATLEN        (200*200)
  55. #define PA(a)        ((a))
  56. #define MA(a)        (256-(a))
  57. #define MYLUM(r,g,b)     ((RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b)+127)>>8)
  58.  
  59. #define LLUM(c)              ((RINTLUM*(c)[OFFSET_R]+            \
  60.               GINTLUM*(c)[OFFSET_G]+             \
  61.               BINTLUM*(c)[OFFSET_B]+127)>>8)
  62. /* lerp macros */
  63.  
  64. #define NLERP(v1,v2,a)        ((v1)+(((((v2)-(v1))*(a))+bloff)>>8))
  65. #define CLERP(v1,v2,ma)     (((v1)*(ma)+(v2))>>8)
  66.  
  67. /* blend macros */
  68.  
  69. #define CLIPROW(d,x,y,n,mat) {                    \
  70.     if(clip) {                        \
  71.         if(y<0 || y>=d->ysize) return;            \
  72.         if(x>=d->xsize) return;                \
  73.         if((x+n)<=0) return;                \
  74.         if((x+n)>d->xsize) n = d->xsize-x;            \
  75.         if(x<0) { n += x; mat -= x; x = 0; }        \
  76.     }                            \
  77. }
  78.  
  79. #define CLIPCOL(d,x,y,n,mat) {                    \
  80.     if(clip) {                        \
  81.         if(x<0 || x>=d->xsize) return;            \
  82.         if(y>=d->ysize) return;                \
  83.         if((y+n)<=0) return;                \
  84.         if((y+n)>d->ysize) n = d->ysize-y;            \
  85.         if(y<0) { n += y; mat -= y; y = 0; }        \
  86.     }                            \
  87. }
  88.  
  89. #define NBLEND(d,r,g,b,a) {                    \
  90.     (d)[OFFSET_R] = NLERP((d)[OFFSET_R],r,a);            \
  91.     (d)[OFFSET_G] = NLERP((d)[OFFSET_G],g,a);            \
  92.     (d)[OFFSET_B] = NLERP((d)[OFFSET_B],b,a);            \
  93. }
  94.  
  95. #define CBLEND(d,r,g,b,ma) {                    \
  96.     (d)[OFFSET_R] = CLERP((d)[OFFSET_R],r,ma);            \
  97.     (d)[OFFSET_G] = CLERP((d)[OFFSET_G],g,ma);            \
  98.     (d)[OFFSET_B] = CLERP((d)[OFFSET_B],b,ma);            \
  99. }
  100.  
  101. #define XBLEND(d,cr,cg,cb,a) {                    \
  102.     v = NLERP((d)[OFFSET_R],cr,a);                \
  103.     if(v&0xff00) {                        \
  104.     if(v<0) v = 0; else v = 255;                \
  105.     }                                \
  106.     (d)[OFFSET_R] = v;                        \
  107.     v = NLERP((d)[OFFSET_G],cg,a);                \
  108.     if(v&0xff00) {                        \
  109.     if(v<0) v = 0; else v = 255;                \
  110.     }                                \
  111.     (d)[OFFSET_G] = v;                        \
  112.     v = NLERP((d)[OFFSET_B],cb,a);                \
  113.     if(v&0xff00) {                        \
  114.     if(v<0) v = 0; else v = 255;                \
  115.     }                                \
  116.     (d)[OFFSET_B] = v;                        \
  117. }
  118.  
  119. /* chromalerp macros */
  120.  
  121. #define NCHROMABLEND() {                        \
  122.     ld = LLUM(dptr);                            \
  123.     curc = (unsigned char *)(chromatab+ld);                \
  124.     r = dptr[OFFSET_R] = NLERP(dptr[OFFSET_R],curc[OFFSET_R],a);    \
  125.     b = dptr[OFFSET_B] = NLERP(dptr[OFFSET_B],curc[OFFSET_B],a);    \
  126.     g = ((ld<<8)-(r*RINTLUM)-(b*BINTLUM)+(GINTLUM/2))/GINTLUM;        \
  127.     if(g&0xff00) {                            \
  128.     if(g<0) g = 0; else g = 255;                    \
  129.     }                                    \
  130.     dptr[OFFSET_G] = g;                                \
  131. }
  132.  
  133. #define XCHROMABLEND() {                        \
  134.     ld = LLUM(dptr);                            \
  135.     curc = (unsigned char *)(chromatab+ld);                \
  136.     r = NLERP(dptr[OFFSET_R],curc[OFFSET_R],a);             \
  137.     if(r&0xff00) {                            \
  138.     if(r<0) r = 0; else r = 255;                    \
  139.     }                                    \
  140.     dptr[OFFSET_R] = r;                            \
  141.     b = NLERP(dptr[OFFSET_B],curc[OFFSET_B],a);             \
  142.     if(b&0xff00) {                            \
  143.     if(b<0) b = 0; else b = 255;                    \
  144.     }                                    \
  145.     dptr[OFFSET_B] = b;                            \
  146.     g = ((ld<<8)-(r*RINTLUM)-(b*BINTLUM)+(GINTLUM/2))/GINTLUM;        \
  147.     if(g&0xff00) {                            \
  148.     if(g<0) g = 0; else g = 255;                    \
  149.     }                                    \
  150.     dptr[OFFSET_G] = g;                                \
  151. }
  152.  
  153. /* on darker macros */
  154.  
  155. #define NONDARKERBLEND() {                    \
  156.     if(LLUM(dptr)<cl)                        \
  157.     NBLEND(dptr,cr,cg,cb,a);                \
  158. }
  159.  
  160. #define XONDARKERBLEND() {                    \
  161.     if(LLUM(dptr)<cl)                        \
  162.     NBLEND(dptr,cr,cg,cb,a);                \
  163. }
  164.  
  165. /* on lighter macros */
  166.  
  167. #define NONLIGHTERBLEND() {                    \
  168.     if(LLUM(dptr)>=cl)                        \
  169.     NBLEND(dptr,cr,cg,cb,a);                \
  170. }
  171.  
  172. #define XONLIGHTERBLEND() {                    \
  173.     if(LLUM(dptr)>=cl)                        \
  174.     NBLEND(dptr,cr,cg,cb,a);                \
  175. }
  176.  
  177. static int negalpha;
  178. static int clonemode;
  179. static unsigned long *chromatab;
  180. static unsigned long *chromatable;
  181. static curb;
  182. static canvas *clonesrc;
  183. static int clonedx, clonedy;
  184. static float fclonedx, fclonedy;
  185. static float eclonedx, eclonedy;
  186. static unsigned long ar, ag, ab, adiv;
  187. static unsigned short curlum;
  188. static unsigned long curchroma;
  189. static long *pixdata;
  190. static long *pixptr;
  191. static int stoff;
  192. static int bloffset;
  193. static unsigned long curcolor;
  194.  
  195. static mybitrev(val)
  196. unsigned int val;
  197. {
  198.     val = ((val>>4 )&0x0f)|((val<<4 )&0xf0);
  199.     val = ((val>>2 )&0x33)|((val<<2 )&0xcc);
  200.     val = ((val>>1 )&0x55)|((val<<1 )&0xaa);
  201.     return val&0xff;
  202. }
  203.  
  204. void beginstroke()
  205. {
  206.     float dx, dy;
  207.     
  208.      bloffset = mybitrev(stoff++);
  209.      dx = fclonedx+eclonedx;
  210.      dy = fclonedy+eclonedy;
  211.      clonedx = round(dx);
  212.      clonedy = round(dy);
  213.      eclonedx = dx-clonedx;
  214.      eclonedy = dy-clonedy;
  215. }
  216.  
  217. void endstroke()
  218. {
  219. }
  220.  
  221. void setnegalpha(v)
  222. int v;
  223. {
  224.     negalpha = v;
  225. }
  226.  
  227. void setclonemode(c)
  228. {
  229.     clonemode = c;
  230. }
  231.  
  232. /*
  233.  *    color handling
  234.  *
  235.  */
  236. void setcurcolor(c)
  237. unsigned long c;
  238. {
  239.     unsigned char *curc, *chro;
  240.     int b, hb;
  241.  
  242.     if(c != curcolor) {
  243.     curcolor = c;
  244.     curc = (unsigned char *)&curcolor;
  245.     curlum = MYLUM(curc[OFFSET_R],curc[OFFSET_G],curc[OFFSET_B]);
  246.     chro = (unsigned char *)&curchroma;
  247.     b = curc[OFFSET_R];
  248.     if(curc[OFFSET_G]>b)
  249.         b = curc[OFFSET_G];
  250.     if(curc[OFFSET_B]>b)
  251.         b = curc[OFFSET_B];
  252.     if(b == 0)
  253.         b = 1;
  254.     hb = b>>1;
  255.     chro[OFFSET_R] = (255*curc[OFFSET_R]+hb)/b;
  256.     chro[OFFSET_G] = (255*curc[OFFSET_G]+hb)/b;
  257.     chro[OFFSET_B] = (255*curc[OFFSET_B]+hb)/b;
  258.     chromatab = 0;
  259.     }
  260. }
  261.  
  262. unsigned long getcurcolor()
  263. {
  264.     return curcolor;
  265. }
  266.  
  267. static makechromatab()
  268. {
  269.     int i, h, clum;
  270.     int r, g, b, a, bloff;
  271.     unsigned char *cptr;
  272.     unsigned char *curc;
  273.  
  274.     if(!chromatable)
  275.     chromatable = (unsigned long *)mymalloc(256*sizeof(long));
  276.     cptr = (unsigned char *)chromatable;
  277.     curc = (unsigned char *)&curcolor;
  278.     r = curc[OFFSET_R];
  279.     g = curc[OFFSET_G];
  280.     b = curc[OFFSET_B];
  281.     clum = curlum;
  282.     h = clum/2;
  283.     bloff = 127;
  284.     for(i=0; i<256; i++) {
  285.     if(i<clum) {
  286.         cptr[OFFSET_R] = (i*r+h)/clum;
  287.         cptr[OFFSET_G] = (i*g+h)/clum;
  288.         cptr[OFFSET_B] = (i*b+h)/clum;
  289.     } else {
  290.         a = PA((256*(i-clum)/(255.0-clum))+0.49);
  291.         cptr[OFFSET_R] = NLERP(r,255,a);
  292.         cptr[OFFSET_G] = NLERP(g,255,a);
  293.         cptr[OFFSET_B] = NLERP(b,255,a);
  294.     }    
  295.     cptr+=4;
  296.     }
  297.     chromatab = chromatable;
  298. }
  299.  
  300. /*
  301.  *    averaging functions follow
  302.  *
  303.  */
  304. void avg_clear()
  305. {
  306.     ar = 0;
  307.     ag = 0;
  308.     ab = 0;
  309.     adiv = 0;
  310. }
  311.  
  312. long avg_get()
  313. {
  314.     if(adiv == 0)
  315.     return 0x808080;
  316.     ar = (255*ar)/adiv;
  317.     ag = (255*ag)/adiv;
  318.     ab = (255*ab)/adiv;
  319.     return ((ab<<16)+(ag<<8)+(ar<<0));
  320. }
  321.  
  322. #define SETDPTR()    dptr = (unsigned char*)&dest->data[x+y*dest->xsize]
  323. #define SETDMAX()    dmax = dptr+n*sizeof(long); 
  324. #define SETCOLDMAX()    dmax = dptr+n*xsize;
  325. #define SETBLOFF()    bloff = bloffset;
  326. #define SETCURC()    curc = (unsigned char *)&curcolor;    \
  327.                 cr = curc[OFFSET_R];            \
  328.                 cg = curc[OFFSET_G];            \
  329.                 cb = curc[OFFSET_B];
  330.  
  331. static void avg_constblendrow(dest,a,x,y,n,clip) 
  332. canvas *dest;
  333. short a;
  334. int x, y, n, clip;
  335. {
  336.     unsigned char *dptr, *dmax, *mat;
  337.     unsigned long lar, lag, lab, ladiv;
  338.     int bloff;
  339.  
  340.     CLIPROW(dest,x,y,n,mat);
  341.     lar = lag = lab = 0;
  342.     ladiv = 255*n;
  343.     SETBLOFF();
  344.     SETDPTR();
  345.     SETDMAX();
  346.     while(dptr != dmax) {
  347.     lar += dptr[OFFSET_R];
  348.     lag += dptr[OFFSET_G];
  349.     lab += dptr[OFFSET_B];
  350.     dptr += 4;
  351.     }
  352.     ar += (a*lar+bloff)>>8;
  353.     ag += (a*lag+bloff)>>8;
  354.     ab += (a*lab+bloff)>>8;
  355.     adiv += (a*ladiv+bloff)>>8;
  356. }
  357.  
  358. static void avg_blendrow(dest,mat,x,y,n,clip) 
  359. canvas *dest;
  360. unsigned char *mat;
  361. int x, y, n, clip;
  362. {
  363.     unsigned char *dptr, *dmax;
  364.     int bloff, a;
  365.     unsigned long lar, lag, lab, ladiv;
  366.  
  367.     CLIPROW(dest,x,y,n,mat);
  368.     lar = lag = lab = ladiv = 0;
  369.     SETBLOFF();
  370.     SETDPTR();
  371.     SETDMAX();
  372.     while(dptr != dmax) {
  373.     a = PA(*mat++);
  374.     if(a) {
  375.         lar += (a*dptr[OFFSET_R]+bloff)>>8;
  376.         lag += (a*dptr[OFFSET_G]+bloff)>>8;
  377.         lab += (a*dptr[OFFSET_B]+bloff)>>8;
  378.         ladiv += a;
  379.     }
  380.     dptr += sizeof(long);
  381.     }
  382.     ar += lar;
  383.     ag += lag;
  384.     ab += lab;
  385.     adiv += ladiv;
  386. }
  387.  
  388. static void avg_blendcol(dest,mat,x,y,n,clip) 
  389. canvas *dest;
  390. unsigned char *mat;
  391. int x, y, n, clip;
  392. {
  393.     unsigned char *dptr, *dmax;
  394.     int bloff, a, xsize;
  395.     unsigned long lar, lag, lab, ladiv;
  396.  
  397.     CLIPCOL(dest,x,y,n,mat);
  398.     lar = lag = lab = ladiv = 0;
  399.     xsize = dest->xsize*sizeof(long);
  400.     SETBLOFF();
  401.     SETDPTR();
  402.     SETCOLDMAX();
  403.     while(dptr != dmax) {
  404.     a = PA(*mat++);
  405.     if(a) {
  406.         lar += (a*dptr[OFFSET_R]+bloff)>>8;
  407.         lag += (a*dptr[OFFSET_G]+bloff)>>8;
  408.         lab += (a*dptr[OFFSET_B]+bloff)>>8;
  409.         ladiv += a;
  410.     }
  411.     dptr += xsize;
  412.     }
  413.     ar += lar;
  414.     ag += lag;
  415.     ab += lab;
  416.     adiv += ladiv;
  417. }
  418.  
  419. /*
  420.  *    rgb blending functions follow
  421.  *
  422.  *
  423.  */
  424. static void rgb_constblendrow(dest,a,x,y,n,clip) 
  425. canvas *dest;
  426. short a;
  427. int x, y, n, clip;
  428. {
  429.     unsigned char *curc, *dptr, *dmax, *mat;
  430.     int v, cr, cg, cb, ma, bloff;
  431.  
  432.     CLIPROW(dest,x,y,n,mat);
  433.     if(clonemode) {
  434.     writepix_constblendrow(dest,a,x,y,n);
  435.     return;
  436.     }
  437.     SETBLOFF();
  438.     SETCURC();
  439.     SETDPTR();
  440.     SETDMAX();
  441.     if(negalpha) {
  442.     a = PA(-a);
  443.     while(dptr != dmax) {
  444.         XBLEND(dptr,cr,cg,cb,a);
  445.         dptr += sizeof(long);
  446.     }
  447.     } else {
  448.     a = PA(a);
  449.     ma = MA(a);
  450.     cr  = (a * curc[OFFSET_R])+bloff;
  451.     cg = (a * curc[OFFSET_G])+bloff;
  452.     cb = (a * curc[OFFSET_B])+bloff;
  453.     while(dptr != dmax) {
  454.         CBLEND(dptr,cr,cg,cb,ma);
  455.         dptr += sizeof(long);
  456.     }
  457.     }
  458. }
  459.  
  460. static void rgb_blendrow(dest,mat,x,y,n,clip) 
  461. canvas *dest;
  462. unsigned char *mat;
  463. int x, y, n, clip;
  464. {
  465.     unsigned char *curc, *dptr, *dmax;
  466.     int a, v, cr, cg, cb, bloff;
  467.  
  468.     CLIPROW(dest,x,y,n,mat);
  469.     if(clonemode) {
  470.     writepix_blendrow(dest,mat,x,y,n);
  471.     return;
  472.     }
  473.     SETBLOFF();
  474.     SETCURC();
  475.     SETDPTR();
  476.     SETDMAX();
  477.     if(negalpha) {
  478.     while(dptr != dmax) {
  479.         a = PA(-(*mat++));
  480.         if(a) 
  481.         XBLEND(dptr,cr,cg,cb,a);
  482.         dptr += sizeof(long);
  483.     }
  484.     } else {
  485.     while(dptr != dmax) {
  486.         a = PA(*mat++);
  487.         if(a) 
  488.         NBLEND(dptr,cr,cg,cb,a);
  489.         dptr += sizeof(long);
  490.     }
  491.     }
  492. }
  493.  
  494. static void rgb_blendcol(dest,mat,x,y,n,clip) 
  495. canvas *dest;
  496. unsigned char *mat;
  497. int x, y, n, clip;
  498. {
  499.     unsigned char *curc, *dptr, *dmax;
  500.     int a, v, cr, cg, cb, xsize, bloff;
  501.  
  502.     CLIPCOL(dest,x,y,n,mat);
  503.     if(clonemode) {
  504.     writepix_blendcol(dest,mat,x,y,n);
  505.     return;
  506.     }
  507.     xsize = dest->xsize*sizeof(long);
  508.     SETBLOFF();
  509.     SETCURC();
  510.     SETDPTR();
  511.     SETCOLDMAX();
  512.     if(negalpha) {
  513.     while(dptr != dmax) {
  514.         a = PA(-((int)(*mat++)));
  515.         if(a)
  516.         XBLEND(dptr,cr,cg,cb,a);
  517.         dptr += xsize;
  518.     }
  519.     } else {
  520.     while(dptr != dmax) {
  521.         a = PA(*mat++);
  522.         if(a) 
  523.         NBLEND(dptr,cr,cg,cb,a);
  524.         dptr += xsize;
  525.     }
  526.     }
  527. }
  528.  
  529. /*
  530.  *    chroma blending functions follow
  531.  *
  532.  *
  533.  */
  534. static void chroma_constblendrow(dest,a,x,y,n,clip) 
  535. canvas *dest;
  536. short a;
  537. int x, y, n, clip;
  538. {
  539.     unsigned char *curc, *dptr, *dmax, *mat;
  540.     int ld, r, g, b, bloff;
  541.  
  542.     CLIPROW(dest,x,y,n,mat);
  543.     if(clonemode) {
  544.     writepix_constblendrow(dest,a,x,y,n);
  545.     return;
  546.     }
  547.     if(!chromatab)
  548.     makechromatab();
  549.     SETBLOFF();
  550.     SETDPTR();
  551.     SETDMAX();
  552.     if(negalpha) {
  553.     a = PA(-a);
  554.     while(dptr != dmax) {
  555.         XCHROMABLEND();
  556.         dptr += sizeof(long);
  557.     }
  558.     } else {
  559.     while(dptr != dmax) {
  560.         NCHROMABLEND();
  561.         dptr += sizeof(long);
  562.     }
  563.     }
  564. }
  565.  
  566. static void chroma_blendrow(dest,mat,x,y,n,clip) 
  567. canvas *dest;
  568. unsigned char *mat;
  569. int x, y, n, clip;
  570. {
  571.     unsigned char *curc, *dptr, *dmax;
  572.     int a, ld, r, g, b, bloff;
  573.  
  574.     CLIPROW(dest,x,y,n,mat);
  575.     if(clonemode) {
  576.     writepix_blendrow(dest,mat,x,y,n);
  577.     return;
  578.     }
  579.     if(!chromatab)
  580.     makechromatab();
  581.     SETBLOFF();
  582.     SETDPTR();
  583.     SETDMAX();
  584.     if(negalpha) {
  585.     while(dptr != dmax) {
  586.         a = PA(-((int)*mat++));
  587.         if(a) 
  588.         XCHROMABLEND();
  589.         dptr += sizeof(long);
  590.     }
  591.     } else {
  592.     while(dptr != dmax) {
  593.         a = PA(*mat++);
  594.         if(a)
  595.         NCHROMABLEND();
  596.         dptr += sizeof(long);
  597.     }
  598.     }
  599. }
  600.  
  601. static void chroma_blendcol(dest,mat,x,y,n,clip) 
  602. canvas *dest;
  603. unsigned char *mat;
  604. int x, y, n, clip;
  605. {
  606.     unsigned char *curc, *dptr, *dmax;
  607.     int a, ld, r, g, b, xsize, bloff;
  608.  
  609.     CLIPCOL(dest,x,y,n,mat);
  610.     if(clonemode) {
  611.     writepix_blendcol(dest,mat,x,y,n);
  612.     return;
  613.     }
  614.     if(!chromatab)
  615.     makechromatab();
  616.     xsize = dest->xsize*sizeof(long);
  617.     SETBLOFF();
  618.     SETDPTR();
  619.     SETCOLDMAX();
  620.     if(negalpha) {
  621.     while(dptr != dmax) {
  622.         a = PA(-((int)*mat++));
  623.         if(a)    
  624.         XCHROMABLEND();
  625.         dptr += xsize;
  626.     }
  627.     } else {
  628.     while(dptr != dmax) {
  629.         a = PA(*mat++);
  630.         if(a) 
  631.         NCHROMABLEND();
  632.         dptr += xsize;
  633.     }
  634.     }
  635. }
  636.  
  637. /*
  638.  *    darker blend follows
  639.  *
  640.  */
  641. static void darker_constblendrow(dest,a,x,y,n,clip) 
  642. canvas *dest;
  643. short a;
  644. int x, y, n, clip;
  645. {
  646.     unsigned char *curc, *dptr, *dmax, *mat;
  647.     int cl, cr, cg, cb, bloff;
  648.  
  649.     CLIPROW(dest,x,y,n,mat);
  650.     if(clonemode) {
  651.     writepix_constblendrow(dest,a,x,y,n);
  652.     return;
  653.     }
  654.     cl = curlum;
  655.     a = PA(a);
  656.     SETBLOFF();
  657.     SETCURC();
  658.     SETDPTR();
  659.     SETDMAX();
  660.     while(dptr != dmax) {
  661.     NONDARKERBLEND();
  662.     dptr += sizeof(long);
  663.     }
  664. }
  665.  
  666. static void darker_blendrow(dest,mat,x,y,n,clip) 
  667. canvas *dest;
  668. unsigned char *mat;
  669. int x, y, n, clip;
  670. {
  671.     unsigned char *curc, *dptr, *dmax;
  672.     int a, ma, cl, cr, cg, cb, bloff;
  673.  
  674.     CLIPROW(dest,x,y,n,mat);
  675.     if(clonemode) {
  676.     writepix_blendrow(dest,mat,x,y,n);
  677.     return;
  678.     }
  679.     cl = curlum;
  680.     SETBLOFF();
  681.     SETCURC();
  682.     SETDPTR();
  683.     SETDMAX();
  684.     while(dptr != dmax) {
  685.     a = PA(*mat++);
  686.     if(a)
  687.         NONDARKERBLEND();
  688.     dptr += sizeof(long);
  689.     }
  690. }
  691.  
  692. static void darker_blendcol(dest,mat,x,y,n,clip) 
  693. canvas *dest;
  694. unsigned char *mat;
  695. int x, y, n, clip;
  696. {
  697.     unsigned char *curc, *dptr, *dmax;
  698.     int a, cl, cr, cg, cb, xsize, bloff;
  699.  
  700.     CLIPCOL(dest,x,y,n,mat);
  701.     if(clonemode) {
  702.     writepix_blendcol(dest,mat,x,y,n);
  703.     return;
  704.     }
  705.     xsize = dest->xsize*sizeof(long);
  706.     cl = curlum;
  707.     SETBLOFF();
  708.     SETCURC();
  709.     SETDPTR();
  710.     SETCOLDMAX();
  711.     while(dptr != dmax) {
  712.     a = PA(*mat++);
  713.     if(a)
  714.         NONDARKERBLEND();
  715.     dptr += xsize;
  716.     }
  717. }
  718.  
  719. /*
  720.  *    lighter blend follows
  721.  *
  722.  */
  723. static void lighter_constblendrow(dest,a,x,y,n,clip) 
  724. canvas *dest;
  725. short a;
  726. int x, y, n, clip;
  727. {
  728.     unsigned char *curc, *dptr, *dmax, *mat;
  729.     int cl, cr, cg, cb, bloff;
  730.  
  731.     CLIPROW(dest,x,y,n,mat);
  732.     if(clonemode) {
  733.     writepix_constblendrow(dest,a,x,y,n);
  734.     return;
  735.     }
  736.     cl = curlum;
  737.     a = PA(a);
  738.     SETBLOFF();
  739.     SETCURC();
  740.     SETDPTR();
  741.     SETDMAX();
  742.     while(dptr != dmax) {
  743.     NONLIGHTERBLEND();
  744.     dptr += sizeof(long);
  745.     }
  746. }
  747.  
  748. static void lighter_blendrow(dest,mat,x,y,n,clip) 
  749. canvas *dest;
  750. unsigned char *mat;
  751. int x, y, n ,clip;
  752. {
  753.     unsigned char *curc, *dptr, *dmax;
  754.     int a, cl, cr, cg, cb, bloff;
  755.  
  756.     CLIPROW(dest,x,y,n,mat);
  757.     if(clonemode) {
  758.     writepix_blendrow(dest,mat,x,y,n);
  759.     return;
  760.     }
  761.     cl = curlum;
  762.     SETBLOFF();
  763.     SETCURC();
  764.     SETDPTR();
  765.     SETDMAX();
  766.     while(dptr != dmax) {
  767.     a = PA(*mat++);
  768.     if(a) 
  769.         NONLIGHTERBLEND();
  770.     dptr += sizeof(long);
  771.     }
  772. }
  773.  
  774. static void lighter_blendcol(dest,mat,x,y,n,clip) 
  775. canvas *dest;
  776. unsigned char *mat;
  777. int x, y, n, clip;
  778. {
  779.     unsigned char *curc, *dptr, *dmax;
  780.     int a, ma, cl, cr, cg, cb, xsize, bloff;
  781.  
  782.     CLIPCOL(dest,x,y,n,mat);
  783.     if(clonemode) {
  784.     writepix_blendcol(dest,mat,x,y,n);
  785.     return;
  786.     }
  787.     cl = curlum;
  788.     xsize = dest->xsize*sizeof(long);
  789.     SETBLOFF();
  790.     SETCURC();
  791.     SETDPTR();
  792.     SETCOLDMAX();
  793.     while(dptr != dmax) {
  794.     a = PA(*mat++);
  795.     if(a) 
  796.         NONLIGHTERBLEND();
  797.     dptr += xsize;
  798.     }
  799. }
  800.  
  801. /*
  802.  *    writepix blend follows
  803.  *
  804.  */
  805. static unsigned char *getwritepixrow()
  806. {
  807.     int n;
  808.     unsigned char *lptr;
  809.  
  810.     n = *pixptr++;
  811.     if(n == NOTHING)
  812.     return 0;
  813.     else {
  814.     lptr = (unsigned char *)pixptr;
  815.     pixptr += n;
  816.     return lptr;
  817.     }
  818. }
  819.  
  820. static void writepix_constblendrow(dest,a,x,y,n) 
  821. canvas *dest;
  822. short a;
  823. int x, y, n;
  824. {
  825.     unsigned char *dptr, *dmax, *sptr;
  826.     int v, bloff;
  827.  
  828.     sptr = getwritepixrow();
  829.     if(!sptr)
  830.     return;
  831.     SETBLOFF();
  832.     SETDPTR();
  833.     SETDMAX();
  834.     if(negalpha) {
  835.     a = PA(-a);
  836.     while(dptr != dmax) {
  837.         XBLEND(dptr,sptr[OFFSET_R],sptr[OFFSET_G],sptr[OFFSET_B],a);
  838.         sptr += sizeof(long);
  839.         dptr += sizeof(long);
  840.     }
  841.     } else {
  842.     a = PA(a);
  843.     while(dptr != dmax) {
  844.         NBLEND(dptr,sptr[OFFSET_R],sptr[OFFSET_G],sptr[OFFSET_B],a);
  845.         sptr += sizeof(long);
  846.         dptr += sizeof(long);
  847.     }
  848.     }
  849. }
  850.  
  851. static void writepix_blendrow(dest,mat,x,y,n) 
  852. canvas *dest;
  853. unsigned char *mat;
  854. int x, y, n;
  855. {
  856.     unsigned char *dptr, *dmax, *sptr;
  857.     int a, v, bloff;
  858.  
  859.     sptr = getwritepixrow();
  860.     if(!sptr)
  861.        return;
  862.     SETBLOFF();
  863.     SETDPTR();
  864.     SETDMAX();
  865.     if(negalpha) {
  866.     while(dptr != dmax) {
  867.         a = PA(-((int)(*mat++)));
  868.         if(a) 
  869.         XBLEND(dptr,sptr[OFFSET_R],sptr[OFFSET_G],sptr[OFFSET_B],a);
  870.         sptr += sizeof(long);
  871.         dptr += sizeof(long);
  872.     }
  873.     } else {
  874.     while(dptr != dmax) {
  875.         a = PA(*mat++);
  876.         if(a)
  877.         NBLEND(dptr,sptr[OFFSET_R],sptr[OFFSET_G],sptr[OFFSET_B],a);
  878.         sptr += sizeof(long);
  879.         dptr += sizeof(long);
  880.     }
  881.     }
  882. }
  883.  
  884. static void writepix_blendcol(dest,mat,x,y,n) 
  885. canvas *dest;
  886. unsigned char *mat;
  887. int x, y, n;
  888. {
  889.     unsigned char *dptr, *dmax, *sptr;
  890.     int a, v, xsize, bloff;
  891.  
  892.     sptr = getwritepixrow();
  893.     if(!sptr)
  894.        return;
  895.     xsize = dest->xsize*sizeof(long);
  896.     SETBLOFF();
  897.     SETDPTR();
  898.     SETCOLDMAX();
  899.     if(negalpha) {
  900.     while(dptr != dmax) {
  901.         a = PA(-((int)(*mat++)));
  902.         if(a)
  903.         XBLEND(dptr,sptr[OFFSET_R],sptr[OFFSET_G],sptr[OFFSET_B],a);
  904.         sptr += sizeof(long);
  905.         dptr += xsize;
  906.     }
  907.     } else {
  908.     while(dptr != dmax) {
  909.         a = PA(*mat++);
  910.         if(a) 
  911.         NBLEND(dptr,sptr[OFFSET_R],sptr[OFFSET_G],sptr[OFFSET_B],a);
  912.         sptr += sizeof(long);
  913.         dptr += xsize;
  914.     }
  915.     }
  916. }
  917.  
  918. /*
  919.  *    readpix stuff follows
  920.  *
  921.  *
  922.  */
  923. void clonesource(c,dx,dy)
  924. canvas *c;
  925. float dx, dy;
  926. {
  927.     clonesrc = c;
  928.     fclonedx = dx;
  929.     fclonedy = dy;
  930. }
  931.  
  932. void readpix_init()
  933. {
  934.     if(!pixdata)
  935.     pixdata = (long *)mymalloc(DATLEN*sizeof(long));
  936.     pixptr = pixdata;
  937. }
  938.  
  939. static int addnothing()
  940. {
  941.     *pixptr++ = NOTHING;
  942. }
  943.  
  944. static saverow(x,y,n)
  945. int x, y, n;
  946. {
  947.     x += clonedx;
  948.     y += clonedy;
  949.     if(!clonesrc || x<0 || x+n>=clonesrc->xsize) {
  950.     addnothing();
  951.      return;
  952.     }
  953.     if(y<0 || y>=clonesrc->ysize) {
  954.     addnothing();
  955.      return;
  956.     }
  957.     *pixptr++ = n;
  958.     bcopy(clonesrc->data+(y*clonesrc->xsize+x),pixptr,n*sizeof(long));
  959.     pixptr += n;
  960. }
  961.  
  962. static savecol(x,y,n)
  963. int x, y, n;
  964. {
  965.     unsigned long *lptr;
  966.     int xsize;
  967.  
  968.     x += clonedx;
  969.     y += clonedy;
  970.     if(!clonesrc || x<0 || x>=clonesrc->xsize) {
  971.     addnothing();
  972.      return;
  973.     }
  974.     if(y<0 || y+n>=clonesrc->ysize) {
  975.     addnothing();
  976.      return;
  977.     }
  978.     *pixptr++ = n;
  979.     lptr = clonesrc->data+(y*clonesrc->xsize+x);
  980.     xsize = clonesrc->xsize;
  981.     while(n--) {
  982.     *pixptr++ = *lptr;
  983.     lptr += xsize;
  984.     }
  985. }
  986.  
  987. static void readpix_constblendrow(dest,a,x,y,n,clip) 
  988. canvas *dest;
  989. short a;
  990. int x, y, n, clip;
  991. {
  992.     unsigned char *mat;
  993.  
  994.     CLIPROW(dest,x,y,n,mat);
  995.     saverow(x,y,n);
  996. }
  997.  
  998. static void readpix_blendrow(dest,mat,x,y,n,clip) 
  999. canvas *dest;
  1000. unsigned char *mat;
  1001. int x, y, n, clip;
  1002. {
  1003.     CLIPROW(dest,x,y,n,mat);
  1004.     saverow(x,y,n);
  1005. }
  1006.  
  1007. static void readpix_blendcol(dest,mat,x,y,n,clip) 
  1008. canvas *dest;
  1009. unsigned char *mat;
  1010. int x, y, n, clip;
  1011. {
  1012.     CLIPCOL(dest,x,y,n,mat);
  1013.     savecol(x,y,n);
  1014. }
  1015.  
  1016. /*
  1017.  *    general setblend function
  1018.  *
  1019.  *
  1020.  */
  1021. void setblend(b)
  1022. int b;
  1023. {
  1024.     curb = b;
  1025.     switch(b) {
  1026.         case BLEND_AVGCOLOR:
  1027.         constblendrow = avg_constblendrow;
  1028.         blendrow = avg_blendrow;
  1029.         blendcol = avg_blendcol;
  1030.         break;
  1031.         case BLEND_RGB:
  1032.         constblendrow = rgb_constblendrow;
  1033.         blendrow = rgb_blendrow;
  1034.         blendcol = rgb_blendcol;
  1035.         break;
  1036.         case BLEND_CHROMA:
  1037.         constblendrow = chroma_constblendrow;
  1038.         blendrow = chroma_blendrow;
  1039.         blendcol = chroma_blendcol;
  1040.         break;
  1041.         case BLEND_DARKER:
  1042.         constblendrow = darker_constblendrow;
  1043.         blendrow = darker_blendrow;
  1044.         blendcol = darker_blendcol;
  1045.         break;
  1046.         case BLEND_LIGHTER:
  1047.         constblendrow = lighter_constblendrow;
  1048.         blendrow = lighter_blendrow;
  1049.         blendcol = lighter_blendcol;
  1050.         break; 
  1051.         case BLEND_READPIX:
  1052.         constblendrow = readpix_constblendrow;
  1053.         blendrow = readpix_blendrow;
  1054.         blendcol = readpix_blendcol;
  1055.         break;
  1056.     }
  1057. }
  1058.  
  1059. int getblend()
  1060. {
  1061.     return curb;
  1062. }
  1063.